#pragma once

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>

#include <iostream>
#include <string>

using namespace boost::asio;
using namespace boost::system;
using namespace std;

extern io_service g_service;

class CTalkToSvr 
	: public boost::enable_shared_from_this<CTalkToSvr>,
	boost::noncopyable
{
private:
	CTalkToSvr(const string & strMsg)
		:m_socketUdp(g_service, ip::udp::endpoint(ip::udp::v4(), 0)), m_strSendMsg(strMsg)
	{

	};
	
public :
	typedef boost::shared_ptr<CTalkToSvr> ptr;
	~CTalkToSvr()
	{

	}

	static void Start(ip::udp::endpoint &ep, char *msg)
	{
		ptr new_(new CTalkToSvr(msg));
		new_->start(ep);
	}

private:
	void start(ip::udp::endpoint &ep)
	{
		m_socketUdp.async_send_to(boost::asio::buffer(m_strSendMsg), ep, 
			boost::bind(&CTalkToSvr::HandlerSendTo, shared_from_this(), _1, _2));
	}

	void HandlerSendTo(const boost::system::error_code & err, size_t bytes)
	{
		if(!err)
		{
			ip::udp::endpoint clientEp;
			m_socketUdp.async_receive_from(buffer(m_recvMsg), clientEp, 
				boost::bind(
				&CTalkToSvr::HandlerReceiveFrom, 
				shared_from_this(),
				_1,
				_2));
		}
		else
		{
			Stop();
		}
	}

	void HandlerReceiveFrom(const boost::system::error_code & err, size_t bytes)
	{
		if(!err)
		{
			if(bytes > 0)
			{
				string strRecvMsg(m_recvMsg, bytes);

				cout << strRecvMsg << " : " << (m_strSendMsg == strRecvMsg ? "OK" : "FAIL") <<endl;
			}
		}
		else
		{
			Stop();
		}
	}

	void Stop()
	{
		m_socketUdp.close();
	}


private:
	ip::udp::socket m_socketUdp;
	
	string m_strSendMsg;
	char m_recvMsg[1024];
};